package com.course.system.controller.admin;

import com.course.common.enums.Constant;
import com.course.common.response.BaseResponse;
import com.course.common.response.StatusCode;
import com.course.common.util.AssertUtil;
import com.course.common.util.JwtUtil;
import com.course.model.dto.LoginUserDto;
import com.course.model.dto.PageDto;
import com.course.model.dto.UserDto;
import com.course.model.service.SendVerifyCodeService;
import com.course.model.service.UserService;
import com.course.model.util.UuidUtil;
import com.course.model.util.ValidatorUtil;
import com.course.system.controller.BaseController;
import com.google.gson.Gson;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/admin/user")
public class UserController extends BaseController {

    public static final String BUSINESS_NAME = "用户";

    @Resource
    private UserService userService;

    @Resource
    private BCryptPasswordEncoder encoder;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    private static Gson GSON = new Gson();

    @Resource
    private RedisTemplate redisTemplate;

    /**
     * 列表查询
     */
    @PostMapping("/getUserList")
    public BaseResponse list(@RequestBody PageDto pageDto, HttpServletRequest request) {
        //获取令牌数据
//        String authorization = request.getHeader("Authorization");
//        logger.info("令牌信息：{}",authorization);

        BaseResponse response = new BaseResponse().sucess();
        userService.list(pageDto);
        response.setData(pageDto);
        return response;
    }

    /**
     * 保存，id有值时更新，无值时新增
     */
    @PostMapping("/save")
    public BaseResponse save(@RequestBody UserDto userDto) {
        //保险方案：对密码进行前后端两层加密
//        userDto.setPassword(DigestUtils.md5DigestAsHex(userDto.getPassword().getBytes()));
        //使用spring-security中的BCryptPasswordEncoder对密码进行加密
        userDto.setPassword(encoder.encode(userDto.getPassword()));
        // 保存校验
        ValidatorUtil.require(userDto.getLoginName(), "登陆名");
        ValidatorUtil.length(userDto.getLoginName(), "登陆名", 1, 50);
        ValidatorUtil.length(userDto.getName(), "昵称", 1, 50);
        ValidatorUtil.require(userDto.getPassword(), "密码");

        BaseResponse response = new BaseResponse().sucess();
        userService.save(userDto);
        response.setData(userDto);
        return response;
    }

    /**
     * 删除
     */
    @DeleteMapping("/delete/{id}")
    public BaseResponse delete(@PathVariable String id) {
        BaseResponse response = new BaseResponse().sucess();
        userService.delete(id);
        return response;
    }

    /**
     * 重置密码
     *
     * @param userDto
     * @return
     */
    @PostMapping("/save-password")
    public BaseResponse savePassword(@RequestBody UserDto userDto) {
        //参数非空校验
        ValidatorUtil.require(userDto.getPassword(), "用户名密码");
        userDto.setPassword(encoder.encode(userDto.getPassword()));
        //logger.info("密码匹配测试：{}",encoder.matches("123456",userDto.getPassword()));
        BaseResponse response = new BaseResponse().sucess();
        userService.savePassword(userDto);
        response.setData(userDto);
        return response;
    }

    /**
     * 用户登录
     *
     * @param userDto
     * @return
     */
    @PostMapping("/login")
    public BaseResponse login(HttpServletRequest req, HttpServletResponse resp, @RequestBody UserDto userDto) {
        logger.info("用户登录开始");
        //参数非空校验
        ValidatorUtil.require(userDto.getPassword(), "用户名密码");
        //logger.info("密码匹配测试：{}",encoder.matches("123456",userDto.getPassword()));
        BaseResponse response = new BaseResponse().sucess();

        //根据验证码token去获取缓存中的验证码，和用户输入的验证码是否一致
        //String imageCode = (String)request.getSession().getAttribute(userDto.getImageCodeToken());
        String imageCode = stringRedisTemplate.opsForValue().get(Constant.REDIS_LOGIN_PREFIX + userDto.getImageCodeToken());
        logger.info("从redis中获取到的验证码：{}", imageCode);
        //从缓存中取出验证码
        if (StringUtils.isEmpty(imageCode) || !imageCode.toLowerCase().equals(userDto.getImageCode().toLowerCase())) {
            //验证码过期/输入有误
            logger.info(StatusCode.ImageCodeFail.getMsg());
            return new BaseResponse().failure(StatusCode.ImageCodeFail.getMsg());
        } else {
            //验证码通过后，移除验证码
            //request.getSession().removeAttribute(userDto.getImageCodeToken());
            stringRedisTemplate.delete(userDto.getImageCodeToken());
        }

        LoginUserDto loginUser = userService.login(userDto);
        String token = UuidUtil.getShortUuid();
        loginUser.setToken(token);
        //对redis中的用户数据进行加密处理-生成令牌
        String userJwt = JwtUtil.createJWT(token, GSON.toJson(loginUser), null);

        //会话保持-集群session:保存在服务端
        //request.getSession().setAttribute(Constant.LOGIN_USER, loginUser);
        redisTemplate.opsForValue().set(Constant.REDIS_LOGIN_PREFIX + token, userJwt, 1, TimeUnit.HOURS);

        //会话保持-Cookie:保存在客户端
        //添加Cookie
//        Cookie cookie = new Cookie("Authorization", userJwt);
//        resp.addCookie(cookie);

        response.setData(loginUser);
        return response;
    }

    /**
     * 退出登录
     *
     * @return
     */
    @GetMapping("/logout/{token}")
    public BaseResponse logout(@PathVariable String token) {
        BaseResponse response = new BaseResponse().sucess();
        //request.getSession().setAttribute("loginUser", null);
        //request.getSession().removeAttribute(Constant.LOGIN_USER);
        redisTemplate.delete(Constant.REDIS_LOGIN_PREFIX + token);
        return response;
    }

    @Resource
    private SendVerifyCodeService sendVerifyCodeService;

    /**
     * 发送验证码
     * @param phone
     * @return
     */
    @GetMapping("send")
    public BaseResponse send(String phone){
        AssertUtil.isNotEmpty(phone,"手机号不能为空!");
        sendVerifyCodeService.send(phone);
        return new BaseResponse().sucess();
    }

//    /**
//     * 登录
//     *
//     * @param account  帐号：用户名或手机或邮箱
//     * @param password 密码
//     * @param path     请求路径
//     * @return
//     */
//    public ResultInfo signIn(String account, String password, String path) {
//        // 参数校验
//        AssertUtil.isNotEmpty(account, "请输入登录帐号");
//        AssertUtil.isNotEmpty(password, "请输入登录密码");
//        // 构建请求头
//        HttpHeaders headers = new HttpHeaders();
//        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
//        // 构建请求体（请求参数）
//        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
//        body.add("username", account);
//        body.add("password", password);
//        body.setAll(BeanUtil.beanToMap(oAuth2ClientConfiguration));
//        HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(body, headers);
//        // 设置 Authorization
//        restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(oAuth2ClientConfiguration.getClientId(),
//                oAuth2ClientConfiguration.getSecret()));
//        // 发送请求
//        ResponseEntity<ResultInfo> result = restTemplate.postForEntity(oauthServerName + "oauth/token", entity, ResultInfo.class);
//        // 处理返回结果
//        AssertUtil.isTrue(result.getStatusCode() != HttpStatus.OK, "登录失败");
//        ResultInfo resultInfo = result.getBody();
//        if (resultInfo.getCode() != ApiConstant.SUCCESS_CODE) {
//            // 登录失败
//            resultInfo.setData(resultInfo.getMessage());
//            return resultInfo;
//        }
//        // 这里的 Data 是一个 LinkedHashMap 转成了域对象 OAuthDinerInfo
//        OAuthDinerInfo dinerInfo = BeanUtil.fillBeanWithMap((LinkedHashMap) resultInfo.getData(),
//                new OAuthDinerInfo(), false);
//        // 根据业务需求返回视图对象
//        LoginDinerInfo loginDinerInfo = new LoginDinerInfo();
//        loginDinerInfo.setToken(dinerInfo.getAccessToken());
//        loginDinerInfo.setAvatarUrl(dinerInfo.getAvatarUrl());
//        loginDinerInfo.setNickname(dinerInfo.getNickname());
//        return ResultInfoUtil.buildSuccess(path, loginDinerInfo);
//    }


}
